package com.settlement.system.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.settlement.system.common.enums.AccountingStatusEnum;
import com.settlement.system.common.exception.BusinessException;
import com.settlement.system.common.util.SecurityUtils;
import com.settlement.system.common.util.StringUtils;
import com.settlement.system.mapper.SysVoucherItemMapper;
import com.settlement.system.mapper.SysVoucherMapper;
import com.settlement.system.model.entity.*;
import com.settlement.system.model.form.SysVoucherForm;
import com.settlement.system.model.query.BillPageQuery;
import com.settlement.system.model.query.SysVoucherItemQuery;
import com.settlement.system.model.query.SysVoucherQuery;
import com.settlement.system.model.vo.SysAccountingProjectVO;
import com.settlement.system.model.vo.SysVoucherImportVo;
import com.settlement.system.model.vo.SysVoucherItemVo;
import com.settlement.system.model.vo.VoucherItem;
import com.settlement.system.service.*;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 凭证主表 服务实现类
 * </p>
 *
 * @author huangrensen
 * @since 2024-08-26
 */
@Service
@RequiredArgsConstructor
public class SysVoucherServiceImpl extends ServiceImpl<SysVoucherMapper, SysVoucher> implements SysVoucherService {

    private final Logger logger = LoggerFactory.getLogger(SysVoucherServiceImpl.class);
    private final SysBillService billService;

    private final SysStoreService storeService;

    private final SysVoucherItemService voucherItemService;
    private final SysVoucherItemMapper voucherItemMapper;

    private final SysCompanyService companyService;

    private final SysBillDateLinkService billDateLinkService;

    private final SysAccountingProjectService accountingProjectService;

    private final SysPlatformService platformService;

    private final SysUserService userService;

    @Override
    public Page<SysVoucher> getPage(SysVoucherQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        if (StringUtils.hasText(queryParams.getVoucherMonth()) && queryParams.getVoucherMonth().startsWith("0")) {
            // 去除前面的0
            queryParams.setVoucherMonth(queryParams.getVoucherMonth().replace("0", ""));
        }
        // 查询数据
        Page<SysVoucher> page = new Page<>(pageNum, pageSize);
        this.baseMapper.getPage(page, queryParams);
        if (page.getRecords().size() > 0) {
            List<Long> userIdList = page.getRecords().stream().map(SysVoucher::getCreateBy).distinct().toList();
            List<SysUser> userList = userService.listByIds(userIdList);
            for (SysVoucher record : page.getRecords()) {
                // 创建人
                userList.stream().filter(user -> Objects.equals(user.getId(), record.getCreateBy())).findFirst().ifPresent(user -> {
                    record.setCreateByName(user.getNickname());
                });
            }
        }
        return page;
    }

    @Override
    public boolean saveSysVoucher(SysVoucherForm sysVoucherForm) {
        SysVoucher sysVoucher = new SysVoucher();
        BeanUtils.copyProperties(sysVoucherForm, sysVoucher);
        sysVoucher.setCreateTime(null);
        return this.saveOrUpdate(sysVoucher);
    }

    @Override
    public SysVoucherForm getSysVoucherFormData(Long id) {
        SysVoucher sysVoucher = this.getById(id);
        SysVoucherForm sysVoucherForm = new SysVoucherForm();
        BeanUtils.copyProperties(sysVoucher, sysVoucherForm);
        return sysVoucherForm;
    }

    @Override
    public boolean deleteSysVoucher(String ids) {
        Assert.isTrue(StringUtils.hasText(ids), "删除的数据为空");
        List<Long> idArray = Arrays.stream(ids.split(",")).map(Long::parseLong).collect(Collectors.toList());
        return this.removeByIds(idArray);
    }

    @Override
    public void importData(List<SysVoucherImportVo> voList) {
        List<SysVoucher> sysVoucherList = new ArrayList<>();
        for (SysVoucherImportVo importVo : voList) {
            SysVoucher sysVoucher = new SysVoucher();
            BeanUtils.copyProperties(importVo, sysVoucher);
            sysVoucherList.add(sysVoucher);
        }
        this.saveOrUpdateBatch(sysVoucherList);
    }

    @Override
    public List<SysVoucherImportVo> findByIds(String idsStr) {
        if (!StringUtils.hasText(idsStr)) {
            return new ArrayList<>();
        }
        List<Long> ids = Arrays.stream(idsStr.split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<SysVoucher> sysVoucherList = this.getBaseMapper().selectBatchIds(ids);
        List<SysVoucherImportVo> voList = new ArrayList<>();
        for (SysVoucher sysVoucher : sysVoucherList) {
            SysVoucherImportVo vo = new SysVoucherImportVo();
            BeanUtils.copyProperties(sysVoucher, vo);
            voList.add(vo);
        }
        return voList;
    }

    @Override
    public void generate(String month, String companyCode) {
        // 获取日期对应月份的最后一天
        LocalDate localDate = LocalDate.parse(month + "01", DateTimeFormatter.ofPattern("yyyyMMdd"));
        String voucherYear = localDate.getYear() + "";
        String voucherMonth = localDate.getMonthValue() + "";
        LocalDate lastDate = localDate.withDayOfMonth(localDate.lengthOfMonth());
        SysCompany company = companyService.getCompanyByCode(companyCode);
        /*logger.info("先按照年月和入账主体删除旧的记录...");
        SysVoucherQuery query = new SysVoucherQuery();
        query.setVoucherYear(voucherYear);
        query.setVoucherMonth(voucherMonth);
        query.setCompanyCode(companyCode);
        query.setPageSize(300);
        Page<SysVoucher> page = this.getPage(query);
        List<Long> idList;
        while (!page.getRecords().isEmpty()) {
            idList = page.getRecords().stream().map(SysVoucher::getId).collect(Collectors.toList());
            // 删除记录
            this.removeByIds(idList);
            // 删除明细
            voucherItemService.getBaseMapper().delete(new LambdaQueryWrapper<SysVoucherItem>().in(SysVoucherItem::getVoucherId, idList));
            // 查询下一页
            query.setPageNum(query.getPageNum() + 1);
            page = this.getPage(query);
        }*/
        logger.info("正在生成凭证...");
        List<SysStore> storeList = storeService.list(new LambdaQueryWrapper<SysStore>().eq(SysStore::getCompanyCode, companyCode));
        if (storeList.size() == 0) {
            throw new BusinessException("根据入账主体编码【%s】找不到店铺...".formatted(companyCode));
        }
        // 生成一条主表记录
        SysVoucher voucher = new SysVoucher();
        // 入账主体编码
        voucher.setCompanyCode(companyCode);
        // 账簿编码=财务系统公司编码
        voucher.setAccountBookId(company.getFinanceCompanyCode());
        // 账簿名称=入账主体全称
        voucher.setAccountBookName(company.getFullName());
        // 日期 格式 yyyy/MM/dd
        voucher.setVoucherDate(LocalDate.now());
        // 业务日期=所选的年月中月份的最后一天
        voucher.setBusinessDate(lastDate.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")));
        // 会计年度
        voucher.setVoucherYear(voucherYear);
        // 记账月
        voucher.setVoucherMonth(voucherMonth);
        // 核算组织编码
        voucher.setOrgId(company.getBookCode());
        // 核算组织名称
        voucher.setOrgName(company.getBookName());
        // 创建人
        voucher.setCreateBy(SecurityUtils.getUserId());
        logger.info("保存凭证主表数据");
        this.save(voucher);
        // 根据storeKey查出所有平台
        List<String> storeKeyList = storeList.stream().map(SysStore::getStoreKey).distinct().toList();
        List<SysPlatform> platformList = platformService.list(new LambdaQueryWrapper<SysPlatform>().in(SysPlatform::getPlatformKey, storeKeyList));
        if (platformList.size() == 0) {
            throw new BusinessException("没有找到平台配置信息...");
        }
        // 根据对账系统平台编码查出记账项目
        List<String> platformCodeList = platformList.stream().map(SysPlatform::getReconciliationSystemCode).toList();
        List<SysAccountingProject> accountingProjectList = accountingProjectService.list(new LambdaQueryWrapper<SysAccountingProject>().in(SysAccountingProject::getBillSystemPlatformCode, platformCodeList));
        if (accountingProjectList.size() == 0) {
            throw new BusinessException("没有找到记账项目配置信息...");
        }
        List<SysAccountingProjectVO> sysAccountingProjectVoList = new ArrayList<>();
        SysAccountingProjectVO sysAccountingProjectVo;
        for (SysAccountingProject sysAccountingProject : accountingProjectList) {
            sysAccountingProjectVo = new SysAccountingProjectVO();
            BeanUtils.copyProperties(sysAccountingProject, sysAccountingProjectVo, "accessory", "otherAccessory");
            // 资金类别
            if (StringUtils.hasText(sysAccountingProject.getFundingProjectsStr())) {
                sysAccountingProjectVo.setFundingProjects(JSONObject.parseObject(sysAccountingProject.getFundingProjectsStr(), Map.class));
            }
            // 辅助项
            if (StringUtils.hasText(sysAccountingProject.getAccessory())) {
                sysAccountingProjectVo.setAccessory(JSONObject.parseObject(sysAccountingProject.getAccessory(), Map.class));
            }
            if (StringUtils.hasText(sysAccountingProject.getOtherAccessory())) {
                sysAccountingProjectVo.setOtherAccessory(JSONObject.parseObject(sysAccountingProject.getOtherAccessory(), Map.class));
            }
            sysAccountingProjectVoList.add(sysAccountingProjectVo);
        }
        List<SysVoucherItem> voucherItems = new ArrayList<>();
        List<SysVoucherItem> createOrUpdateList;
        List<Long> storeIdList = storeList.stream().map(SysStore::getId).toList();
        logger.info("需要查询的店铺列表：{}", storeIdList);
        List<SysBillDateLink> dateLinkList = billDateLinkService.list(new LambdaQueryWrapper<SysBillDateLink>().in(SysBillDateLink::getStoreId, storeIdList));
        logger.info("过滤当前选择的月份：{}", month);
        dateLinkList = dateLinkList.stream().filter(link -> Objects.equals(link.getBillDateMonth(), month)).toList();
        logger.info("当前入账主体跟当前出账日期【{}】相等的存在以下表中...", month);
        List<String> tableNameList = dateLinkList.stream().map(SysBillDateLink::getTableName).distinct().toList();
        logger.info(String.join(",", tableNameList));
        logger.info("正在每个表拉取数据生成凭证...");
        BillPageQuery queryParams;
        SysVoucherItem voucherItem;
        SysStore store;
        SysPlatform platform;
        SysAccountingProjectVO accountingProjectVo;
        for (String tableName : tableNameList) {
            queryParams = new BillPageQuery();
            logger.info("正在拉取表【{}】的数据...", tableName);
            queryParams.setPageSize(300);
            queryParams.setTableName(tableName);
            queryParams.setStoreIdList(storeIdList);
            logger.info("查询第{}页的数据...", queryParams.getPageNum());
            Page<SysBill> billPage = billService.getAllBillPage(queryParams);
            while (billPage.getRecords().size() > 0) {
                createOrUpdateList = new ArrayList<>();
                for (SysBill record : billPage.getRecords()) {
                    // 店铺
                    store = storeList.stream().filter(item -> Objects.equals(item.getId(), record.getStoreId())).findFirst().orElse(null);
                    if (Objects.isNull(store)) {
                        logger.info("此账单ID【{}】找不到对应的店铺...", record.getId());
                        continue;
                    }
                    String storeKey = store.getStoreKey();
                    // 平台
                    platform = platformList.stream().filter(item -> Objects.equals(item.getPlatformKey(), storeKey)).findFirst().orElse(null);
                    if (Objects.isNull(platform)) {
                        logger.info("此账单ID【{}】找不到对应的平台...", record.getId());
                        continue;
                    }
                    String reconciliationSystemCode = platform.getReconciliationSystemCode();
                    // 按照【电商平台项目名称】和【对账系统平台编码】找到记账项目配置
                    accountingProjectVo = sysAccountingProjectVoList.stream().filter(item -> Objects.equals(item.getBillSystemPlatformCode(), reconciliationSystemCode) && Objects.equals(item.getAccountingProjectName(), record.getOriginalBillProject())).findFirst().orElse(null);
                    if (Objects.isNull(accountingProjectVo)) {
                        logger.info("此账单ID【{}】找不到对应的记账项目配置...", record.getId());
                        continue;
                    }
                    if (!accountingProjectVo.getFundingProjects().containsKey("资金项目类别1") || !StringUtils.hasText(accountingProjectVo.getFundingProjects().get("资金项目类别1"))) {
                        logger.info("此账单ID【{}】没有配置到资金项目类别1...", record.getId());
                        continue;
                    }
                    if (!Objects.equals(AccountingStatusEnum.YES.getValue(), accountingProjectVo.getAccounting())) {
                        logger.info("此账单ID【{}】不参与记账...", record.getId());
                        continue;
                    }
                    // 按照【资金项目类别1】和【借贷方向】查找【借方】的凭证明细
                    String fundsType = accountingProjectVo.getFundingProjects().get("资金项目类别1");
                    voucherItem = voucherItems.stream().filter(item -> Objects.nonNull(fundsType)
                            && Objects.nonNull(item.getFundsType())
                            && Objects.equals(item.getFundsType().replaceAll("\\+", "").replaceAll("-", "").strip(), fundsType.replaceAll("\\+", "").replaceAll("-", "").strip())
                            && Objects.equals(item.getBorrowing(), "借")).findFirst().orElse(null);
                    if (Objects.isNull(voucherItem)) {
                        voucherItem = new SysVoucherItem();
                    }
                    voucherItem.setVoucherId(voucher.getId());
                    fillVoucherItem(voucherItem, accountingProjectVo, record, platform, store, fundsType, "借", month);
                    voucherItem.setDebitAmount(voucherItem.getAmount());
                    createOrUpdateList.add(voucherItem);
                    // 按照【资金项目类别1】和【借贷方向】查找【贷方】的凭证明细
                    voucherItem = voucherItems.stream().filter(item -> Objects.nonNull(item.getFundsType())
                            && Objects.nonNull(fundsType)
                            && Objects.equals(item.getFundsType().replaceAll("\\+", "").replaceAll("-", "").strip(), fundsType.replaceAll("\\+", "").replaceAll("-", "").strip())
                            && Objects.equals(item.getBorrowing(), "贷")).findFirst().orElse(null);
                    if (Objects.isNull(voucherItem)) {
                        voucherItem = new SysVoucherItem();
                    }
                    voucherItem.setVoucherId(voucher.getId());
                    fillVoucherItem(voucherItem, accountingProjectVo, record, platform, store, fundsType, "贷", month);
                    voucherItem.setDebitAmount(voucherItem.getAmount());
                    createOrUpdateList.add(voucherItem);
                }
                if (createOrUpdateList.size() > 0) {
                    logger.info("保存凭证明细...");
                    voucherItemService.saveOrUpdateBatch(createOrUpdateList);
                }
                // 更新总表记录
                if (voucherItems.size() == 0) {
                    voucherItems.addAll(createOrUpdateList);
                } else {
                    for (SysVoucherItem sysVoucherItem : createOrUpdateList) {
                        voucherItems.removeIf(item -> Objects.equals(item.getFundsType(), sysVoucherItem.getFundsType()));
                    }
                    voucherItems.addAll(createOrUpdateList);
                }
                // 查询下一页
                queryParams.setPageNum(queryParams.getPageNum() + 1);
                logger.info("查询第{}页的数据，总页数：{}", queryParams.getPageNum(), billPage.getPages());
                billPage = billService.getAllBillPage(queryParams);
            }
        }
    }

    @Override
    public List<SysVoucherImportVo> findByMonth(String voucherYear, String voucherMonth) {
        List<SysVoucherImportVo> voList = new ArrayList<>();
        SysVoucherQuery queryParams = new SysVoucherQuery();
        if (voucherMonth.startsWith("0")) {
            voucherMonth = voucherMonth.replace("0", "");
        }
        queryParams.setVoucherYear(voucherYear);
        queryParams.setVoucherMonth(voucherMonth);
        queryParams.setPageSize(300);
        Page<SysVoucher> page = this.getPage(queryParams);
        List<SysVoucher> dataList;
        List<SysVoucherItem> dataItemList;
        List<Long> ids;
        SysVoucher voucher;
        SysVoucherImportVo importVo;
        Map<Long, List<SysVoucherItem>> listMap;
        VoucherItem vItem;
        while (page.getRecords().size() > 0) {
            dataList = page.getRecords();
            ids = dataList.stream().map(SysVoucher::getId).collect(Collectors.toList());
            dataItemList = voucherItemService.list(new LambdaQueryWrapper<SysVoucherItem>().in(SysVoucherItem::getVoucherId, ids));
            listMap = dataItemList.stream().collect(Collectors.groupingBy(SysVoucherItem::getVoucherId));
            for (Long id : listMap.keySet()) {
                dataItemList = listMap.get(id);
                for (SysVoucherItem voucherItem : dataItemList) {
                    voucher = dataList.stream().filter(item -> Objects.equals(item.getId(), id)).findFirst().get();
                    importVo = new SysVoucherImportVo();
                    BeanUtils.copyProperties(voucher, importVo);
                    BeanUtils.copyProperties(voucherItem, importVo);
                    // 银行
                    vItem = getItemVo(voucherItem.getBank());
                    importVo.setBankCode(vItem.getCode());
                    importVo.setBankName(vItem.getName());
                    // 银行账号
                    vItem = getItemVo(voucherItem.getBankAccount());
                    importVo.setBankAccountCode(vItem.getCode());
                    importVo.setBankAccountName(vItem.getName());
                    // 部门
                    vItem = getItemVo(voucherItem.getDept());
                    importVo.setDeptCode(vItem.getCode());
                    importVo.setDeptName(vItem.getName());
                    // 供应商
                    vItem = getItemVo(voucherItem.getSupplier());
                    importVo.setSupplierCode(vItem.getCode());
                    importVo.setSupplierName(vItem.getName());
                    // 客户
                    vItem = getItemVo(voucherItem.getCustomer());
                    importVo.setCustomerCode(vItem.getCode());
                    importVo.setCustomerName(vItem.getName());
                    // 原币金额
                    importVo.setAmount(Objects.nonNull(voucherItem.getAmount()) ? voucherItem.getAmount().toString() : "");
                    // 借方金额
                    importVo.setDebitAmount(Objects.nonNull(voucherItem.getDebitAmount()) ? voucherItem.getDebitAmount().toString() : "");
                    // 贷方金额
                    importVo.setCreditAmount(Objects.nonNull(voucherItem.getCreditAmount()) ? voucherItem.getCreditAmount().toString() : "");
                    voList.add(importVo);
                }
            }
            // 查询下一页
            queryParams.setPageNum(queryParams.getPageNum() + 1);
            page = this.getPage(queryParams);
        }
        return voList;
    }

    /**
     * 填充凭证明细
     *
     * @param voucherItem         凭证明细
     * @param accountingProjectVo 入账主体配置
     * @param bill                标准账单
     * @param platform            平台
     * @param store               店铺
     * @param fundsType           资金项目类别1
     * @param borrowing           借贷方向
     * @param month               年月
     */
    private void fillVoucherItem(SysVoucherItem voucherItem, SysAccountingProjectVO accountingProjectVo, SysBill bill, SysPlatform platform, SysStore store, String fundsType, String borrowing, String month) {
        // 资金项目类别1
        if(StringUtils.hasText(fundsType)){
            voucherItem.setFundsType(fundsType.replaceAll("\\+", "").replaceAll("-", "").strip());
        }
        // 借贷方向
        voucherItem.setBorrowing(borrowing);
        // 摘要
        String explanation;
        // 辅助项值
        String accessoryValue;
        // 店铺名称
        String storeName = store.getCommercePlatformStoreName();
        // 按照借贷方向找到记账项目配置中对应的借方或贷方的配置
        if (Objects.equals(borrowing, accountingProjectVo.getBorrowing())) {
            // 取发生方的配置信息
            // 摘要（格式：平台-末级科目名称-税率-期间）
            // 平台：标准账单中的平台
            //末级科目名称：标准账单中，资金项目类别1对应的费用项的借方末级科目编码，到科目配置中找到末级科目名称。
            //税率：标准账单中，资金项目类别1对应的费用项对应的税率。
            //期间：生成报表时，所选择的年月
            explanation = "%s-%s-%s-%s".formatted(platform.getReconciliationSystemName(), accountingProjectVo.getLastName(), accountingProjectVo.getRate(), month);
            voucherItem.setExplanation(checkSame(explanation, voucherItem.getExplanation()));
            // 末级科目编码
            voucherItem.setLastCode(checkSame(accountingProjectVo.getLastCode(), voucherItem.getLastCode()));
            // 一级科目名称
            voucherItem.setFirstName(checkSame(accountingProjectVo.getFirstName(), voucherItem.getFirstName()));
            // 末级科目名称
            voucherItem.setLastName(checkSame(accountingProjectVo.getLastName(), voucherItem.getLastName()));
            // 辅助项-银行：取当前店铺的辅助项配置
            accessoryValue = getValueFromAccessory("银行", storeName, accountingProjectVo.getAccessory());
            voucherItem.setBank(checkSame(accessoryValue, voucherItem.getBank()));
            // 辅助项-银行末级：取当前店铺的辅助项配置
            accessoryValue = getValueFromAccessory("银行末级", storeName, accountingProjectVo.getAccessory());
            voucherItem.setBankAccount(checkSame(accessoryValue, voucherItem.getBankAccount()));
            // 辅助项-部门：取当前店铺的辅助项配置
            accessoryValue = getValueFromAccessory("部门", storeName, accountingProjectVo.getAccessory());
            voucherItem.setDept(checkSame(accessoryValue, voucherItem.getDept()));
            // 辅助项-供应商：取当前店铺的辅助项配置
            accessoryValue = getValueFromAccessory("供应商", storeName, accountingProjectVo.getAccessory());
            voucherItem.setSupplier(checkSame(accessoryValue, voucherItem.getSupplier()));
            // 辅助项-客户：取当前店铺的辅助项配置
            accessoryValue = getValueFromAccessory("客户", storeName, accountingProjectVo.getAccessory());
            voucherItem.setCustomer(checkSame(accessoryValue, voucherItem.getCustomer()));
        } else if (Objects.equals(borrowing, accountingProjectVo.getOtherAccountingProject())) {
            // 取对方的配置信息
            explanation = "%s-%s-%s-%s".formatted(platform.getReconciliationSystemName(), accountingProjectVo.getOtherLastName(), accountingProjectVo.getRate(), month);
            voucherItem.setExplanation(checkSame(explanation, voucherItem.getExplanation()));
            // 末级科目编码
            voucherItem.setLastCode(checkSame(accountingProjectVo.getOtherLastCode(), voucherItem.getLastCode()));
            // 一级科目名称
            voucherItem.setFirstName(checkSame(accountingProjectVo.getOtherFirstName(), voucherItem.getFirstName()));
            // 末级科目名称
            voucherItem.setLastName(checkSame(accountingProjectVo.getOtherLastName(), voucherItem.getLastName()));
            // 辅助项-银行：取当前店铺的辅助项配置
            accessoryValue = getValueFromAccessory("银行", storeName, accountingProjectVo.getOtherAccessory());
            voucherItem.setBank(checkSame(accessoryValue, voucherItem.getBank()));
            // 辅助项-银行末级：取当前店铺的辅助项配置
            accessoryValue = getValueFromAccessory("银行末级", storeName, accountingProjectVo.getOtherAccessory());
            voucherItem.setBankAccount(checkSame(accessoryValue, voucherItem.getBankAccount()));
            // 辅助项-部门：取当前店铺的辅助项配置
            accessoryValue = getValueFromAccessory("部门", storeName, accountingProjectVo.getOtherAccessory());
            voucherItem.setDept(checkSame(accessoryValue, voucherItem.getDept()));
            // 辅助项-供应商：取当前店铺的辅助项配置
            accessoryValue = getValueFromAccessory("供应商", storeName, accountingProjectVo.getOtherAccessory());
            voucherItem.setSupplier(checkSame(accessoryValue, voucherItem.getSupplier()));
            // 辅助项-客户：取当前店铺的辅助项配置
            accessoryValue = getValueFromAccessory("客户", storeName, accountingProjectVo.getOtherAccessory());
            voucherItem.setCustomer(checkSame(accessoryValue, voucherItem.getCustomer()));
        }
        // 原币金额：计算公式按照记账项目的【资金项目计算方向】计算
        if(StringUtils.hasText(fundsType)){
            if (fundsType.endsWith("-")) {
                voucherItem.setAmount(voucherItem.getAmount().subtract(bill.getBillAmount()));
            } else if (fundsType.endsWith("+")) {
                voucherItem.setAmount(voucherItem.getAmount().add(bill.getBillAmount()));
            }else{
                // 默认加
                voucherItem.setAmount(voucherItem.getAmount().add(bill.getBillAmount()));
            }
        }

    }

    /**
     * 检查字段值是否不一样
     * 如同一个资金项目类别1，对应的多个费用项的其他属性值有多值的情况，表格中该位置显示“统计异常，存在多值！”
     *
     * @param newText     新的文本值
     * @param sourceValue 原始值
     * @return
     */
    private String checkSame(String newText, String sourceValue) {
        if (StringUtils.hasText(sourceValue)) {
            if (StringUtils.hasText(newText)) {
                if (!Objects.equals(newText, sourceValue)) {
                    return "统计异常，存在多值！";
                } else {
                    return sourceValue;
                }
            } else {
                return sourceValue;
            }
        } else {
            return newText;
        }
    }

    /**
     * 从辅助项中获取值
     *
     * @param key       辅助项key
     * @param storeName 店铺名称
     * @param accessory 辅助项
     * @return
     */
    private String getValueFromAccessory(String key, String storeName, Map<String, Map<String, String>> accessory) {
        if (Objects.nonNull(accessory) && accessory.containsKey(storeName)) {
            if (Objects.nonNull(accessory.get(storeName)) && accessory.get(storeName).containsKey(key)) {
                return accessory.get(storeName).get(key);
            }
        }
        return null;
    }

    @Override
    public Page<SysVoucherItemVo> getItems(Long voucherId, SysVoucherItemQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        // 查询数据
        Page<SysVoucherItem> page = new Page<>(pageNum, pageSize);
        queryParams.setVoucherId(voucherId);
        voucherItemMapper.getPage(page, queryParams);
        Page<SysVoucherItemVo> pageVo = new Page<>(pageNum, pageSize);
        BeanUtils.copyProperties(page, pageVo);
        List<SysVoucherItemVo> voList = new ArrayList<>();
        SysVoucherItemVo vo;
        if (page.getRecords().size() > 0) {
            for (SysVoucherItem sysVoucherItem : page.getRecords()) {
                vo = new SysVoucherItemVo();
                BeanUtils.copyProperties(sysVoucherItem, vo);
                // 银行
                vo.setBank(getItemVo(sysVoucherItem.getBank()));
                // 银行账号
                vo.setBankAccount(getItemVo(sysVoucherItem.getBankAccount()));
                // 部门
                vo.setDept(getItemVo(sysVoucherItem.getDept()));
                // 供应商
                vo.setSupplier(getItemVo(sysVoucherItem.getSupplier()));
                // 客户
                vo.setCustomer(getItemVo(sysVoucherItem.getCustomer()));
                voList.add(vo);
            }
        }
        pageVo.setRecords(voList);
        return pageVo;
    }

    /**
     * 获取明细Item（按照“/”切割，code取前面的值，name取最后的值）
     * @param content 明细内容
     * @return
     */
    private VoucherItem getItemVo(String content) {
        VoucherItem voItem = new VoucherItem();
        if (StringUtils.hasText(content)) {
            String[] splitData = content.split("/");
            voItem.setCode(splitData[0]);
            voItem.setName(splitData[splitData.length - 1]);
        }
        return voItem;
    }
}
